import os
import argparse

def create_directory(path):
    """创建目录，如果目录不存在"""
    if not os.path.exists(path):
        os.makedirs(path)
        print(f"创建目录: {path}")
    else:
        print(f"目录已存在: {path}")

def create_file(path, content=""):
    """创建文件，如果文件不存在"""
    if not os.path.exists(path):
        with open(path, "w") as f:
            f.write(content)
        print(f"创建文件: {path}")
    else:
        print(f"文件已存在: {path}")

def create_project_structure(project_name):
    """创建 C 和 Python 项目目录结构，不创建顶层目录"""

    # C 部分
    c_dir = "c"
    create_directory(c_dir)

    c_include_dir = os.path.join(c_dir, "include")
    create_directory(c_include_dir)

    c_src_dir = os.path.join(c_dir, "src")
    create_directory(c_src_dir)

    create_file(os.path.join(c_src_dir, "main.c"),
                """#include <stdio.h>
#include "plugin_manager.h"

int main() {
    // 1. 创建插件管理器
    PluginManager* manager = create_plugin_manager("plugins"); // 假设插件目录是 "plugins"
    if (!manager) {
        fprintf(stderr, "Failed to create plugin manager.\\n");
        return 1;
    }

    // 2. 加载插件
    PluginHandle plugin_handle = load_plugin(manager, "example_plugin"); // 假设插件名为 "example_plugin"
    if (!plugin_handle) {
        fprintf(stderr, "Failed to load plugin.\\n");
        destroy_plugin_manager(manager);
        return 1;
    }

    // 3. 启动插件
    if(!start_plugin(manager, plugin_handle)){
        fprintf(stderr, "Failed to start plugin.\\n");
        unload_plugin(manager, plugin_handle);
        destroy_plugin_manager(manager);
        return 1;
    }

    // 4. 这里可以调用插件提供的功能...
    printf("Plugin loaded and started successfully.\\n");

    // 5. 停止插件
    stop_plugin(manager, plugin_handle);

    // 6. 卸载插件
    unload_plugin(manager, plugin_handle);

    // 7. 销毁插件管理器
    destroy_plugin_manager(manager);

    printf("Exiting application.\\n");
    return 0;
}
""")
    create_file(os.path.join(c_src_dir, "plugin_manager.c"),
                """#include "plugin_manager.h"
#include <stdio.h>
#include <string.h>
#include <dlfcn.h>

#define INITIAL_CAPACITY 4

// 创建插件管理器
PluginManager* create_plugin_manager(const char* plugin_dir) {
    PluginManager* manager = (PluginManager*)malloc(sizeof(PluginManager));
    if (manager == NULL) {
        perror("Failed to allocate memory for PluginManager");
        return NULL;
    }

    manager->plugin_dir = strdup(plugin_dir); // 复制插件目录字符串
    if (manager->plugin_dir == NULL) {
        perror("Failed to allocate memory for plugin_dir");
        free(manager);
        return NULL;
    }

    manager->plugins = NULL;
    manager->plugin_count = 0;
    manager->plugin_capacity = 0;

    return manager;
}

// 销毁插件管理器
void destroy_plugin_manager(PluginManager* manager) {
    if (manager) {
        // 先卸载所有插件
        for(int i = 0; i < manager->plugin_count; ++i){
            if(manager->plugins[i].state != PLUGIN_STATE_UNLOADED){
                unload_plugin(manager, manager->plugins[i].handle);
            }
        }
        if(manager->plugins){
            free(manager->plugins);
        }
        if (manager->plugin_dir) {
            free(manager->plugin_dir);
        }
        free(manager);
    }
}

// 辅助函数：查找插件
static LoadedPlugin* find_plugin(PluginManager* manager, PluginHandle handle) {
    for (int i = 0; i < manager->plugin_count; ++i) {
        if (manager->plugins[i].handle == handle) {
            return &manager->plugins[i];
        }
    }
    return NULL;
}

// 加载插件
PluginHandle load_plugin(PluginManager* manager, const char* plugin_name) {
    char plugin_path[256]; // 假设插件路径长度不超过 256
    snprintf(plugin_path, sizeof(plugin_path), "%s/%s.so", manager->plugin_dir, plugin_name);

    // 1. 打开动态链接库
    void* handle = dlopen(plugin_path, RTLD_NOW);
    if (!handle) {
        fprintf(stderr, "Failed to load plugin: %s, error: %s\\n", plugin_path, dlerror());
        return NULL;
    }

    // 2. 获取插件的 get_info 函数
    PluginGetInfoFunc get_info = (PluginGetInfoFunc)dlsym(handle, "get_plugin_info");
    if (!get_info) {
        fprintf(stderr, "Failed to find get_plugin_info function in plugin: %s\\n", plugin_path);
        dlclose(handle);
        return NULL;
    }

    // 3. 获取插件信息
    PluginInfo info = get_info();
    printf("Loaded plugin: %s, Description: %s, API Version: %d\\n", info.name, info.description, info.api_version);

    // 4. 获取插件的 load 函数
    PluginLoadFunc load = (PluginLoadFunc)dlsym(handle, "plugin_load");
    if (!load) {
        fprintf(stderr, "Failed to find plugin_load function in plugin: %s\\n", plugin_path);
        dlclose(handle);
        return NULL;
    }

    // 5. 获取插件的 unload 函数
    PluginUnloadFunc unload = (PluginUnloadFunc)dlsym(handle, "plugin_unload");
    if (!unload) {
        fprintf(stderr, "Failed to find plugin_unload function in plugin: %s\\n", plugin_path);
        dlclose(handle);
        return NULL;
    }

    // 6. 获取插件的 start 函数
    PluginStartFunc start = (PluginStartFunc)dlsym(handle, "plugin_start");
    if (!start) {
        fprintf(stderr, "Failed to find plugin_start function in plugin: %s\\n", plugin_path);
        dlclose(handle);
        return NULL;
    }

    // 7. 获取插件的 stop 函数
    PluginStopFunc stop = (PluginStopFunc)dlsym(handle, "plugin_stop");
    if (!stop) {
        fprintf(stderr, "Failed to find plugin_stop function in plugin: %s\\n", plugin_path);
        dlclose(handle);
        return NULL;
    }

    // 8. 执行插件的 load 函数
    PluginHandle plugin_handle;
    if(!load(&plugin_handle)){
        fprintf(stderr, "Failed to load plugin: %s\\n", plugin_path);
        dlclose(handle);
        return NULL;
    }

    // 9. 添加到插件数组
    if (manager->plugin_count == manager->plugin_capacity) {
        manager->plugin_capacity = manager->plugin_capacity == 0 ? INITIAL_CAPACITY : manager->plugin_capacity * 2;
        manager->plugins = (LoadedPlugin*)realloc(manager->plugins, sizeof(LoadedPlugin) * manager->plugin_capacity);
        if (!manager->plugins) {
            perror("Failed to reallocate memory for plugins array");
            dlclose(handle);
            return NULL;
        }
    }

    LoadedPlugin* new_plugin = &manager->plugins[manager->plugin_count++];
    new_plugin->info = info;
    new_plugin->handle = plugin_handle;  // 使用插件返回的句柄
    new_plugin->state = PLUGIN_STATE_LOADED;

    return plugin_handle; // 返回插件的句柄，不再是动态链接库句柄
}

// 卸载插件
void unload_plugin(PluginManager* manager, PluginHandle handle) {
    LoadedPlugin* plugin = find_plugin(manager, handle);

    if (!plugin) {
        fprintf(stderr, "Plugin with handle %p not found.\\n", handle);
        return;
    }

    if (plugin->state == PLUGIN_STATE_STARTED) {
        stop_plugin(manager, handle); // 先停止插件
    }
     //1. 获取动态链接库句柄
    char plugin_path[256]; // 假设插件路径长度不超过 256
    snprintf(plugin_path, sizeof(plugin_path), "%s/%s.so", manager->plugin_dir, plugin->info.name);

    void* dylib_handle = dlopen(plugin_path, RTLD_NOW);
    if (!dylib_handle) {
        fprintf(stderr, "Failed to open dynamic library for unloading.\\n");
        return;
    }

    if (plugin->handle) {
        // 1. 获取插件的 unload 函数
        PluginUnloadFunc unload = (PluginUnloadFunc)dlsym(dylib_handle, "plugin_unload");
        if (!unload) {
            fprintf(stderr, "Failed to find plugin_unload function for unloading.\\n");
            return;
        }

        // 2. 调用卸载函数
        unload(handle);

        // 3. 关闭动态链接库
        dlclose(dylib_handle);
       // plugin->handle = NULL;
        plugin->state = PLUGIN_STATE_UNLOADED;

        printf("Unloaded plugin: %s\\n", plugin->info.name);
    }
}

// 启动插件
bool start_plugin(PluginManager* manager, PluginHandle handle) {
    LoadedPlugin* plugin = find_plugin(manager, handle);

    if (!plugin) {
        fprintf(stderr, "Plugin with handle %p not found.\\n", handle);
        return false;
    }

    if (plugin->state != PLUGIN_STATE_LOADED && plugin->state != PLUGIN_STATE_STOPPED) {
        fprintf(stderr, "Plugin %s cannot be started in its current state.\\n", plugin->info.name);
        return false;
    }

      //1. 获取动态链接库句柄
    char plugin_path[256]; // 假设插件路径长度不超过 256
    snprintf(plugin_path, sizeof(plugin_path), "%s/%s.so", manager->plugin_dir, plugin->info.name);
    void* dylib_handle = dlopen(plugin_path, RTLD_NOW);
    if (!dylib_handle) {
        fprintf(stderr, "Failed to open dynamic library for starting.\\n");
        return false;
    }

    PluginStartFunc start = (PluginStartFunc)dlsym(dylib_handle, "plugin_start");
    if (!start) {
        fprintf(stderr, "Failed to find plugin_start function.\\n");
        return false;
    }

    if (!start(handle)) {
        fprintf(stderr, "Failed to start plugin %s.\\n", plugin->info.name);
        return false;
    }

    plugin->state = PLUGIN_STATE_STARTED;
    printf("Started plugin: %s\\n", plugin->info.name);
    return true;
}

// 停止插件
void stop_plugin(PluginManager* manager, PluginHandle handle) {
    LoadedPlugin* plugin = find_plugin(manager, handle);

    if (!plugin) {
        fprintf(stderr, "Plugin with handle %p not found.\\n", handle);
        return;
    }

    if (plugin->state != PLUGIN_STATE_STARTED) {
        fprintf(stderr, "Plugin %s is not running.\\n", plugin->info.name);
        return;
    }

   //1. 获取动态链接库句柄
    char plugin_path[256]; // 假设插件路径长度不超过 256
    snprintf(plugin_path, sizeof(plugin_path), "%s/%s.so", manager->plugin_dir, plugin->info.name);
    void* dylib_handle = dlopen(plugin_path, RTLD_NOW);
    if (!dylib_handle) {
        fprintf(stderr, "Failed to open dynamic library for stopping.\\n");
        return;
    }

    PluginStopFunc stop = (PluginStopFunc)dlsym(dylib_handle, "plugin_stop");
    if (!stop) {
        fprintf(stderr, "Failed to find plugin_stop function.\\n");
        return;
    }

    stop(handle);
    plugin->state = PLUGIN_STATE_STOPPED;

    printf("Stopped plugin: %s\\n", plugin->info.name);
}
""")
    create_file(os.path.join(c_include_dir, "plugin.h"),
                """#ifndef PLUGIN_H
#define PLUGIN_H

#include <stdbool.h>

// 插件状态枚举类型
typedef enum {
    PLUGIN_STATE_UNLOADED, // 未加载
    PLUGIN_STATE_LOADED,   // 已加载
    PLUGIN_STATE_STARTED,  // 已启动
    PLUGIN_STATE_STOPPED   // 已停止
} PluginState;

// 插件信息结构体
typedef struct {
    const char* name;       // 插件名称
    const char* description; // 插件描述
    int api_version;        // 插件 API 版本
} PluginInfo;

// 插件句柄类型
typedef void* PluginHandle;

// 插件加载函数类型
typedef bool (*PluginLoadFunc)(PluginHandle* handle);

// 插件卸载函数类型
typedef bool (*PluginUnloadFunc)(PluginHandle handle);

// 插件启动函数类型
typedef bool (*PluginStartFunc)(PluginHandle handle);

// 插件停止函数类型
typedef bool (*PluginStopFunc)(PluginHandle handle);

// 获取插件信息函数类型
typedef PluginInfo (*PluginGetInfoFunc)();

// 定义插件结构体
typedef struct {
    PluginLoadFunc load;        // 加载函数
    PluginUnloadFunc unload;      // 卸载函数
    PluginStartFunc start;       // 启动函数
    PluginStopFunc stop;       // 停止函数
    PluginGetInfoFunc get_info; // 获取插件信息函数
} Plugin;

#endif // PLUGIN_H
""")
    create_file(os.path.join(c_include_dir, "plugin_manager.h"),
                """#ifndef PLUGIN_MANAGER_H
#define PLUGIN_MANAGER_H

#include <stdlib.h>
#include <dlfcn.h> // 用于动态链接库操作
#include "plugin.h"

// 定义插件信息结构体
typedef struct {
    PluginInfo info; // 插件信息
    PluginHandle handle; // 动态链接库句柄
    PluginState state;   // 插件状态
} LoadedPlugin;

// 定义插件管理器的结构体
typedef struct {
    char* plugin_dir;    // 插件目录
    LoadedPlugin* plugins; // 插件数组
    int plugin_count;    // 插件数量
    int plugin_capacity; // 插件容量
} PluginManager;

// 创建插件管理器
PluginManager* create_plugin_manager(const char* plugin_dir);

// 销毁插件管理器
void destroy_plugin_manager(PluginManager* manager);

// 加载插件
PluginHandle load_plugin(PluginManager* manager, const char* plugin_name);

// 卸载插件
void unload_plugin(PluginManager* manager, PluginHandle handle);

// 启动插件
bool start_plugin(PluginManager* manager, PluginHandle handle);

// 停止插件
void stop_plugin(PluginManager* manager, PluginHandle handle);

#endif // PLUGIN_MANAGER_H
""")

    # Python 部分
    python_dir = "python"
    create_directory(python_dir)

    python_module_dir = os.path.join(python_dir, project_name.lower()) #创建与项目名同名的python模块
    create_directory(python_module_dir)

    create_file(os.path.join(python_module_dir, "__init__.py"), "")
    create_file(os.path.join(python_module_dir, "example.py"),
                """def hello():
    print("Hello from Python!")
""")

    # 插件部分
    plugins_dir = "plugins"
    create_directory(plugins_dir)
    create_file(os.path.join(plugins_dir, "example_plugin.c"),
                """#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "plugin.h"

// 插件私有数据结构
typedef struct {
    int data;
} ExamplePluginData;

// 获取插件信息
PluginInfo get_plugin_info() {
    PluginInfo info = {
        .name = "Example Plugin",
        .description = "A simple example plugin",
        .api_version = 1
    };
    return info;
}

// 插件加载函数
bool plugin_load(PluginHandle* handle) {
    ExamplePluginData* data = (ExamplePluginData*)malloc(sizeof(ExamplePluginData));
    if (data == NULL) {
        perror("Failed to allocate memory for plugin data");
        return false;
    }
    data->data = 123;
    *handle = (PluginHandle)data; // 将数据指针作为插件句柄返回
    printf("Plugin loaded successfully.\\n");
    return true;
}

// 插件卸载函数
bool plugin_unload(PluginHandle handle) {
    ExamplePluginData* data = (ExamplePluginData*)handle;
    if (data != NULL) {
        free(data);
        printf("Plugin unloaded successfully.\\n");
        return true;
    }
    return false;
}

// 插件启动函数
bool plugin_start(PluginHandle handle) {
    ExamplePluginData* data = (ExamplePluginData*)handle;
    printf("Plugin started with data: %d\\n", data->data);
    return true;
}

// 插件停止函数
bool plugin_stop(PluginHandle handle) {
    printf("Plugin stopped.\\n");
    return true;
}

// 导出插件接口
PluginInfo get_plugin_info(void);
bool plugin_load(PluginHandle* handle);
bool plugin_unload(PluginHandle handle);
bool plugin_start(PluginHandle handle);
bool plugin_stop(PluginHandle handle);

__attribute__((visibility("default"))) PluginInfo get_plugin_info(void) {
  return get_plugin_info();
}

__attribute__((visibility("default"))) bool plugin_load(PluginHandle* handle) {
  return plugin_load(handle);
}

__attribute__((visibility("default"))) bool plugin_unload(PluginHandle handle) {
  return plugin_unload(handle);
}

__attribute__((visibility("default"))) bool plugin_start(PluginHandle handle) {
  return plugin_start(handle);
}

__attribute__((visibility("default"))) bool plugin_stop(PluginHandle handle) {
  return plugin_stop(handle);
}
""")

    # 构建脚本
    create_file("SConstruct",
                """# SConstruct

import os
from SCons.Script import *

env = Environment()

# -----------------------------------------------------------------------------
#  C 部分
# -----------------------------------------------------------------------------

c_src_files = Glob('c/src/*.c')
c_includes = ['c/include']

env.Append(CPPPATH=c_includes)  # 添加头文件搜索路径
env.Append(LIBS=['dl']) # 链接 dl

# 构建可执行文件
program = env.Program('microgui', c_src_files)

# -----------------------------------------------------------------------------
#  Python 部分 (可选，取决于你是否需要构建 Python 模块)
# -----------------------------------------------------------------------------

# 如果你需要构建 Python 模块，可以使用 env.SharedLibrary 和 env.Command 来编译 Python 扩展
# 具体步骤取决于你使用的 Python/C 接口库 (例如 pybind11 或 Cython)

# -----------------------------------------------------------------------------
#  插件部分
# -----------------------------------------------------------------------------

plugin_src_files = Glob('plugins/*.c') # 或者 Glob('plugins/*.cpp')，取决于你的插件语言

# 构建动态链接库 (插件)
for src_file in plugin_src_files:
    plugin_name = os.path.splitext(os.path.basename(str(src_file)))[0] # 获取插件名称 (不带扩展名)
    plugin = env.SharedLibrary(os.path.join('plugins', plugin_name), src_file, SHLIBPREFIX='')

# -----------------------------------------------------------------------------
#  安装 (可选)
# -----------------------------------------------------------------------------

# 如果你需要安装可执行文件和插件，可以使用 Install
# Install('/usr/local/bin', program) # 安装可执行文件到 /usr/local/bin 目录
# Install('/usr/local/lib/microgui/plugins', 'plugins') # 安装插件到 /usr/local/lib/microgui/plugins 目录
""")

    # 其他文件
    create_file("README.md",
                f"""# {project_name}
A mixed C and Python project.
""")

if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="创建 C 和 Python 项目目录结构")
    parser.add_argument("project_name", help="项目名称")
    args = parser.parse_args()

    create_project_structure(args.project_name)
    print(f"项目目录结构创建完成 (没有顶层目录)")
